{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "导入一些用到的库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "tf.logging.set_verbosity(tf.logging.ERROR)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "加载数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting ./train-images-idx3-ubyte.gz\n",
      "Extracting ./train-labels-idx1-ubyte.gz\n",
      "Extracting ./t10k-images-idx3-ubyte.gz\n",
      "Extracting ./t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "mnist = input_data.read_data_sets(\"./\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "定义训练网络"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = tf.placeholder(tf.float32, [None, 784], name='x')\n",
    "y = tf.placeholder(tf.int64, [None], name='y')\n",
    "learning_rate = tf.placeholder(tf.float32, name='learning_rate')\n",
    "keep_prob = tf.placeholder(tf.float32,name = 'keep_prob')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "after 100 training steps, the loss is 0.335999, the validation accuracy is 0.9364\n",
      "after 200 training steps, the loss is 0.2437, the validation accuracy is 0.9604\n",
      "after 300 training steps, the loss is 0.0496813, the validation accuracy is 0.9592\n",
      "after 400 training steps, the loss is 0.166859, the validation accuracy is 0.9634\n",
      "after 500 training steps, the loss is 0.10661, the validation accuracy is 0.9704\n",
      "after 600 training steps, the loss is 0.0458535, the validation accuracy is 0.9784\n",
      "after 700 training steps, the loss is 0.0861818, the validation accuracy is 0.9796\n",
      "after 800 training steps, the loss is 0.139074, the validation accuracy is 0.9808\n",
      "after 900 training steps, the loss is 0.0360201, the validation accuracy is 0.9822\n",
      "after 1000 training steps, the loss is 0.0211539, the validation accuracy is 0.9816\n",
      "after 1100 training steps, the loss is 0.0289816, the validation accuracy is 0.9828\n",
      "after 1200 training steps, the loss is 0.00853879, the validation accuracy is 0.984\n",
      "after 1300 training steps, the loss is 0.00962109, the validation accuracy is 0.9842\n",
      "after 1400 training steps, the loss is 0.0155712, the validation accuracy is 0.9848\n",
      "after 1500 training steps, the loss is 0.0352886, the validation accuracy is 0.9846\n",
      "after 1600 training steps, the loss is 0.00218441, the validation accuracy is 0.9848\n",
      "after 1700 training steps, the loss is 0.0408439, the validation accuracy is 0.9852\n",
      "after 1800 training steps, the loss is 0.0190989, the validation accuracy is 0.9842\n",
      "after 1900 training steps, the loss is 0.0356709, the validation accuracy is 0.9852\n",
      "after 2000 training steps, the loss is 0.00883527, the validation accuracy is 0.9852\n",
      "the training is finish!\n",
      "the test accuarcy is: 0.9832\n"
     ]
    }
   ],
   "source": [
    "def initialize(shape, stddev=0.1):\n",
    "  return tf.truncated_normal(shape, stddev=0.1)\n",
    "\n",
    "L1_units_count = 784\n",
    "\n",
    "W_1 = tf.Variable(initialize([784, L1_units_count]))\n",
    "b_1 = tf.Variable(initialize([L1_units_count]))\n",
    "logits_1 = tf.matmul(x, W_1) + b_1\n",
    "#output_1 = tf.nn.relu(logits_1)\n",
    "output_1 = tf.nn.swish(logits_1)\n",
    "output_drop_1 = tf.nn.dropout(output_1,keep_prob)\n",
    "\n",
    "L2_units_count = 784 \n",
    "W_2 = tf.Variable(initialize([L1_units_count, L2_units_count]))\n",
    "b_2 = tf.Variable(initialize([L2_units_count]))\n",
    "logits_2 = tf.matmul(output_drop_1, W_2) + b_2  \n",
    "#output_2 = tf.nn.relu(logits_2)\n",
    "output_2 = tf.nn.swish(logits_2)\n",
    "output_drop_2 = tf.nn.dropout(output_2,keep_prob)\n",
    "\n",
    "L3_units_count = 10\n",
    "W_3 = tf.Variable(initialize([L2_units_count, L3_units_count]))\n",
    "b_3 = tf.Variable(initialize([L3_units_count]))\n",
    "logits_3 = tf.matmul(output_drop_2, W_3) + b_3  \n",
    "\n",
    "logits = logits_3\n",
    "\n",
    "cross_entropy_loss = tf.reduce_mean(\n",
    "    tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=y))\n",
    "\n",
    "optimizer = tf.train.AdamOptimizer(\n",
    "    learning_rate=learning_rate).minimize(cross_entropy_loss)\n",
    "\n",
    "pred = tf.nn.softmax(logits)\n",
    "correct_pred = tf.equal(tf.argmax(pred, 1), y)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))\n",
    "\n",
    "batch_size = 100\n",
    "trainig_step = 2000\n",
    "lr_base = 0.001\n",
    "kp = 1.0\n",
    "\n",
    "saver = tf.train.Saver()\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "\n",
    "    #定义验证集与测试集\n",
    "    validate_data = {\n",
    "        x: mnist.validation.images,\n",
    "        y: mnist.validation.labels,\n",
    "        keep_prob: kp\n",
    "    }\n",
    "    test_data = {\n",
    "        x: mnist.test.images, \n",
    "        y: mnist.test.labels, \n",
    "        keep_prob: kp\n",
    "    }\n",
    "\n",
    "    for i in range(trainig_step):\n",
    "        lr = lr_base * 0.33333333 ** (i // 500)\n",
    "           \n",
    "        xs, ys = mnist.train.next_batch(batch_size)\n",
    "        _, loss = sess.run(\n",
    "            [optimizer, cross_entropy_loss],\n",
    "            feed_dict={\n",
    "                x: xs,\n",
    "                y: ys,\n",
    "                learning_rate: lr,\n",
    "                keep_prob: kp\n",
    "            })\n",
    "\n",
    "        #每100次训练打印一次损失值与验证准确率\n",
    "        if (i+1) % 100 == 0:\n",
    "            validate_accuracy = sess.run(accuracy, feed_dict=validate_data)\n",
    "            print(\n",
    "                \"after %d training steps, the loss is %g, the validation accuracy is %g\"\n",
    "                % (i+1, loss, validate_accuracy))\n",
    "            saver.save(sess, './model.ckpt', global_step=i+1)\n",
    "\n",
    "    print(\"the training is finish!\")\n",
    "    #最终的测试准确率\n",
    "    acc = sess.run(accuracy, feed_dict=test_data)\n",
    "    print(\"the test accuarcy is:\", acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.0\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x576 with 16 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "with tf.Session() as sess:\n",
    "    ckpt = tf.train.get_checkpoint_state('./')\n",
    "    if ckpt and ckpt.model_checkpoint_path:\n",
    "        saver.restore(sess, ckpt.model_checkpoint_path)\n",
    "        final_pred, acc = sess.run(\n",
    "            [pred, accuracy],\n",
    "            feed_dict={\n",
    "                x: mnist.test.images[:16],\n",
    "                y: mnist.test.labels[:16],\n",
    "                keep_prob: kp\n",
    "            })\n",
    "        orders = np.argsort(final_pred)\n",
    "        plt.figure(figsize=(8, 8))\n",
    "        print(acc)\n",
    "        for idx in range(16):\n",
    "            order = orders[idx, :][-1]\n",
    "            prob = final_pred[idx, :][order]\n",
    "            plt.subplot(4, 4, idx + 1)\n",
    "            plt.axis('off')\n",
    "            plt.title('{}: [{}]-[{:.1f}%]'.format(mnist.test.labels[idx],\n",
    "                                                  order, prob * 100))\n",
    "            plt.imshow(mnist.test.images[idx].reshape((28, 28)))\n",
    "\n",
    "    else:\n",
    "        pass"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "优化过程：\n",
    "1. 分段调整学习率, 效果不明显，后期得不到很好的收敛\n",
    "2. 更换激活函数为switsh，优化算法为Adam，缺省学习率，效果一般，前期收敛速度变快\n",
    "3. 增加一个隐层，效果一般\n",
    "4. 增加神经元数量，每个隐层500个，准确率有提高，96%到97%左右\n",
    "5. 进一步调整学习率，准确率有所提高，能够达到97.5%左右\n",
    "6. 增加神经元，每层神经元增加到与输入特征数量相等，准确率略有提升\n",
    "7. 增加dropout, 各层保留80%输出，准确率明显降低\n",
    "7. 增加训练次数，准确率依然在97.5%左右\n",
    "8. 增加batch_size到100，收敛速度明显变快，最终准确率达到98.2%左右\n",
    "9. 降低隐层神经元数量到500，最终测试准确率略低于98%，还原神经元数量\n",
    "\n",
    "总结：\n",
    "1. 合适的激活函数和优化方法可以加快学习收敛速度\n",
    "2. 足够的隐层神经元数量很重要\n",
    "3. 在未过拟合的情况下dropout效果不明显\n",
    "4. 调整学习率能使学习后期有稳定的收敛速度\n",
    "5. 增加batch_size有明显学习效果\n",
    "6. 总学习数据量超过了训练集的数据总量，说明在不同的参数下反复使用相同的数据训练也是有效果的"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
